import os
import sys
from io import BytesIO
from win32 import win32clipboard
from PySide6.QtWidgets import (
    QApplication,
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListWidget,
    QPushButton,
    QFileDialog,
    QComboBox,
    QMenu,
    QAbstractItemView,
)
from PySide6 import QtCore
from PySide6.QtGui import (
    QBitmap,
    QPainter,
    QPen,
    QBrush,
    QScreen,
    QAction,
    QCursor,
    QPixmap,
)
from PySide6.QtCore import Qt, QPoint, QRect
from PIL import ImageQt

from utils.data import Code, CodeTemplate, Fragment
from ui.SettingWindow import SettingWindow, InitLineEdit


class MainUI(QWidget):
    addCode = QtCore.Signal()
    searchCode = QtCore.Signal()
    addTemplate = QtCore.Signal()
    searchCodeByQRCode = QtCore.Signal()
    searchCodeByScreen = QtCore.Signal()
    QRCodeListItemDelete = QtCore.Signal()
    QRCodeListItemClicked = QtCore.Signal()
    deleteTemplate = QtCore.Signal()
    updateSelectedTemplate = QtCore.Signal()

    def __init__(self):
        super().__init__()
        self.initUI()

    def showSettingWindow(self):
        self.settingWindow = SettingWindow()
        self.settingWindow.addTemplate.connect(self.addTemplate.emit)
        self.settingWindow.show()

    def initUI(self):
        # 设置整体布局
        layout = QVBoxLayout()

        # 添加顶部展示区域
        top_layout = QHBoxLayout()
        self.selected_template = QComboBox()
        # self.formula_edit.setMaximumHeight(100)
        # self.selected_template.setAlignment(Qt.AlignCenter)
        self.selected_template.currentIndexChanged.connect(
            lambda i: self.updateSelectedTemplate.emit()
        )
        top_layout.addWidget(self.selected_template)

        self.delete_template_button = QPushButton("删除当前模板")
        self.delete_template_button.setMaximumWidth(100)
        self.delete_template_button.clicked.connect(self.deleteTemplate.emit)
        top_layout.addWidget(self.delete_template_button)

        self.setting_button = QPushButton("增加模板")
        self.setting_button.setMaximumWidth(100)
        self.setting_button.clicked.connect(self.showSettingWindow)
        top_layout.addWidget(self.setting_button)

        layout.addLayout(top_layout)

        # 添加输入区域
        input_layout = QHBoxLayout()
        input_layout.addWidget(QLabel("输入编号:"))
        self.input_edit = CodeInputEdit()
        # self.input_edit.setMaximumHeight(100)
        input_layout.addWidget(self.input_edit)

        self.input_edit_button = QPushButton("添加编号")
        self.input_edit_button.clicked.connect(self.addCode.emit)
        input_layout.addWidget(self.input_edit_button)
        layout.addLayout(input_layout)

        # 添加查询区域
        search_layout = QHBoxLayout()
        search_layout.addWidget(QLabel("查询编号:"))
        self.search_edit = QLineEdit()
        # self.search_edit.setMaximumHeight(100)
        self.search_edit.returnPressed.connect(self.searchCode.emit)
        search_layout.addWidget(self.search_edit)

        self.search_edit_button = QPushButton("查询编号")
        self.search_edit_button.clicked.connect(self.searchCode.emit)
        search_layout.addWidget(self.search_edit_button)

        self.search_by_picture_button = QPushButton("二维码查询")
        self.search_by_picture_button.clicked.connect(self.searchCodeByQRCode.emit)
        search_layout.addWidget(self.search_by_picture_button)

        self.search_by_screen = QPushButton("截图查询")
        self.search_by_screen.clicked.connect(self.searchCodeByScreen.emit)
        search_layout.addWidget(self.search_by_screen)

        layout.addLayout(search_layout)

        # 添加底部布局
        bottom_layout = QHBoxLayout()

        # 添加二维码显示区域
        bottom_left_layout = QVBoxLayout()
        self.showQRCode = ShowQRCode()
        bottom_left_layout.addWidget(self.showQRCode)
        bottom_layout.addLayout(bottom_left_layout)

        # 添加底部右侧布局
        bottom_right_layout = QVBoxLayout()

        # 显示已存储的二维码
        self.showStoredCode = ShowStoredCode()
        self.showStoredCode.ItemDoubleClicked.connect(self.QRCodeListItemClicked.emit)
        self.showStoredCode.QRCodeListItemDelete.connect(self.QRCodeListItemDelete.emit)
        bottom_right_layout.addWidget(self.showStoredCode)

        bottom_layout.addLayout(bottom_right_layout)
        layout.addLayout(bottom_layout)

        self.setLayout(layout)
        self.setWindowTitle("编号管理")
        self.setGeometry(100, 100, 800, 600)


class ShowQRCode(QWidget):
    def __init__(self):
        super().__init__()
        self.code = None
        self.layout = QVBoxLayout()

        self.template_info = QLabel()
        self.info_message = QLabel()
        self.info_message2 = QLabel()

        self.qr_code = QLabel(self)
        self.qr_code.setAlignment(Qt.AlignCenter)
        self.qr_code.setMinimumSize(400, 400)

        button_layout = QHBoxLayout()
        self.qr_code_save = QPushButton("保存二维码")
        self.qr_code_save.clicked.connect(self.SaveQRCode)
        self.qr_code_copy = QPushButton("复制到剪切板")
        self.qr_code_copy.clicked.connect(self.CopyQRCode)
        self.change_file_name = QPushButton("修改文件名")
        self.change_file_name.clicked.connect(self.ChangeFileName)

        button_layout.addWidget(self.qr_code_save)
        button_layout.addWidget(self.qr_code_copy)
        button_layout.addWidget(self.change_file_name)

        self.layout.addWidget(self.template_info)
        self.layout.addWidget(self.info_message)
        self.layout.addWidget(self.info_message2)
        self.layout.addWidget(self.qr_code)
        self.layout.addLayout(button_layout)
        # self.layout.addWidget(self.qr_code_save)
        self.setLayout(self.layout)

    def update(self, code: Code):
        self.code = code
        img = code.getQRCode()
        qim = ImageQt.toqimage(img)
        pix = QPixmap.fromImage(qim)
        self.qr_code.setPixmap(pix)
        self.info_message.setText(f"编号：{str(code)}")
        self.info_message2.setText(f"生成时间：{code.addTime}")
        template_info_text = ""
        for idx, fragment in enumerate(code.fragments):
            template_info_text += fragment.name
            if idx < len(code.separators):
                template_info_text += code.separators[idx]
        self.template_info.setText("模板信息：" + template_info_text)

    def SaveQRCode(self):
        pixmap = self.qr_code.pixmap()
        filePath, _ = QFileDialog.getSaveFileName(
            self, "Save Image", "", "Image files (*.png *.jpg)"
        )
        if filePath:
            pixmap.save(filePath)

    def CopyQRCode(self):
        pixmap = self.qr_code.pixmap()
        img = ImageQt.fromqpixmap(pixmap)
        output = BytesIO()
        img.save(output, "BMP")
        data = output.getvalue()[14:]
        output.close()
        win32clipboard.OpenClipboard()
        win32clipboard.EmptyClipboard()
        win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
        win32clipboard.CloseClipboard()

    def ChangeFileName(self):
        filename = str(self.code)
        filePath, _ = QFileDialog.getOpenFileName(self)
        path, name = os.path.split(filePath)
        _, suffix = name.rsplit(".", 1)
        newFilePath = path + "/" + filename + "." + suffix
        os.rename(filePath, newFilePath)
        print(newFilePath)


class ShowStoredCode(QWidget):
    ItemDoubleClicked = QtCore.Signal()
    QRCodeListItemDelete = QtCore.Signal()

    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout()
        self.qr_code_list = QListWidget()
        self.qr_code_list.setSelectionMode(QAbstractItemView.MultiSelection)
        self.qr_code_list.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.qr_code_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.qr_code_list.contextMenuPolicy()
        self.qr_code_list.customContextMenuRequested[QtCore.QPoint].connect(
            self.rightMenuShow
        )
        self.layout.addWidget(self.qr_code_list)
        self.setLayout(self.layout)

    def itemDoubleClicked(self, item):
        self.qr_code_list.setCurrentItem(item)
        for subItem in self.qr_code_list.selectedItems():
            if subItem != item:
                subItem.setSelected(False)

        self.ItemDoubleClicked.emit()

    def rightMenuShow(self, pos):
        def deleteCode():
            self.QRCodeListItemDelete.emit()

        popMenu = QMenu()
        popMenu.addAction(QAction("删除", self, triggered=deleteCode))

        popMenu.exec_(QCursor.pos())

    def clear(self):
        self.qr_code_list.clear()

    def addItem(self, item):
        self.qr_code_list.addItem(item)

    def currentItem(self):
        return self.qr_code_list.currentItem()

    def selectedItems(self):
        return self.qr_code_list.selectedItems()


class CodeInputEdit(QWidget):
    def __init__(self):
        super().__init__()
        self.codeTemplate = None
        self.inPutEdit_list = []
        self.separator_list = []
        self.layout = QHBoxLayout()
        self.setLayout(self.layout)

    def update(self, template: CodeTemplate):
        self.codeTemplate = template
        for widget in self.inPutEdit_list:
            widget.deleteLater()
        for widget in self.separator_list:
            widget.deleteLater()
        self.inPutEdit_list = []
        self.separator_list = []

        for index, fragment in enumerate(template.fragments):
            fragmentWidget = InitLineEdit()
            fragmentWidget.dateFormate = template.dateFormate
            fragmentWidget.updateType(fragment.type)
            # fragmentWidget.setPlaceholderText(fragment.name)
            fragmentWidget.setMaxLength(fragment.length)

            self.inPutEdit_list.append(fragmentWidget)
            self.layout.addWidget(fragmentWidget)

            if index < len(template.fragments) - 1:
                separatorWidget = QLabel(template.separators[index])
                self.separator_list.append(separatorWidget)
                self.layout.addWidget(separatorWidget)

    def getCode(self):
        fragments = []
        for index, fragmentWidget in enumerate(self.inPutEdit_list):
            fragments.append(
                Fragment(
                    length=len(fragmentWidget.text()),
                    type=self.codeTemplate.fragments[index].type,
                    string=fragmentWidget.text(),
                    name=self.codeTemplate.fragments[index].name,
                )
            )
        separators = self.codeTemplate.separators.copy()
        dateFormate = self.codeTemplate.dateFormate
        return Code(fragments, separators, dateFormate)


class WScreenShot(QWidget):
    def __init__(self, parent=None, mainCanve=None):
        super(WScreenShot, self).__init__(parent)
        self.mainCanve = mainCanve
        self.showFullScreen()
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setStyleSheet("""background-color:black; """)
        self.setWindowOpacity(0.6)
        desktopRect = QScreen.availableGeometry(QApplication.primaryScreen())
        self.setGeometry(desktopRect)
        self.setCursor(Qt.CrossCursor)
        self.blackMask = QBitmap(desktopRect.size())
        self.blackMask.fill(Qt.black)
        self.mask = self.blackMask.copy()
        self.isDrawing = False
        self.startPoint = QPoint()
        self.endPoint = QPoint()

    def paintEvent(self, event):
        if self.isDrawing:
            self.mask = self.blackMask.copy()
            pp = QPainter(self.mask)
            pen = QPen()
            pen.setStyle(Qt.NoPen)
            pp.setPen(pen)
            brush = QBrush(Qt.white)
            pp.setBrush(brush)
            pp.drawRect(QRect(self.startPoint, self.endPoint))
            self.setMask(QBitmap(self.mask))

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.startPoint = event.pos()
            self.endPoint = self.startPoint
            self.isDrawing = True

    def mouseMoveEvent(self, event):
        if self.isDrawing:
            self.endPoint = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.endPoint = event.pos()
            screenshot = QApplication.primaryScreen().grabWindow(0)
            rect = QRect(self.startPoint, self.endPoint)
            outputRegion = screenshot.copy(rect)
            # outputRegion.save("./sho54t.jpg", format="JPG", quality=100)
            self.mainCanve.screenShotPix = outputRegion
            self.mainCanve.SearchCodeByScreen()
            self.close()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    math_plot = MainUI()
    math_plot.show()
    sys.exit(app.exec_())
